package org.liufeng.weixin.util;  
  
import java.io.BufferedReader;  
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.OutputStream;  
import java.net.ConnectException;  
import java.net.HttpURLConnection;
import java.net.URL;  
  
import javax.activation.MimetypesFileTypeMap;
import javax.net.ssl.HttpsURLConnection;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.SSLSocketFactory;  
import javax.net.ssl.TrustManager;  
  
import net.sf.json.JSONObject;  
  
import org.json.JSONException;
import org.junit.Test;
import org.liufeng.weixin.pojo.AccessToken;
import org.liufeng.weixin.pojo.Menu;
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
/** 
 * 公众平台通用接口工具类 
 *  
 * @author liuyq 
 * @date 2013-08-09 
 */  
public class WeixinUtil {  
    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);  
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";  
    public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";  
    public static String menu_list_url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
    public static String menu_delete_url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
        									    
    public static String send_templateMsg_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
    public static String send_getUserMsg_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    public final static String upload_add_material = "http://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN";
    /** 
     * 发起https请求并获取结果 
     *  
     * @param requestUrl 请求地址 
     * @param requestMethod 请求方式（GET、POST） 
     * @param outputStr 提交的数据 
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
     */  
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
        JSONObject jsonObject = null;  
        StringBuffer buffer = new StringBuffer();  
        try {  
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化   
            TrustManager[] tm = { new MyX509TrustManager() };  
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
            sslContext.init(null, tm, new java.security.SecureRandom());  
            // 从上述SSLContext对象中得到SSLSocketFactory对象   
            SSLSocketFactory ssf = sslContext.getSocketFactory();  
  
            URL url = new URL(requestUrl);  
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
            httpUrlConn.setSSLSocketFactory(ssf);  
  
            httpUrlConn.setDoOutput(true);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  
            // 设置请求方式（GET/POST）   
            httpUrlConn.setRequestMethod(requestMethod);  
  
            if ("GET".equalsIgnoreCase(requestMethod))  
                httpUrlConn.connect();  
  
            // 当有数据需要提交时   
            if ( (null != outputStr)&& (!"".equals(outputStr))) {  
                OutputStream outputStream = httpUrlConn.getOutputStream();  
                // 注意编码格式，防止中文乱码   
                outputStream.write(outputStr.getBytes("UTF-8"));  
                outputStream.close();  
            }  
  
            // 将返回的输入流转换成字符串   
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
  
            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 释放资源   
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  
            jsonObject = JSONObject.fromObject(buffer.toString());  
        } catch (ConnectException ce) {  
            log.error("Weixin server connection timed out.");  
        } catch (Exception e) {  
            log.error("https request error:{}", e);  
        }  
        return jsonObject;  
    }
    
    public static AccessToken getAccessToken(String appid, String appsecret) {  
        AccessToken accessToken = null;  
      
        String requestUrl = access_token_url.replace("APPID", appid).replace("SECRET", appsecret);  
        System.out.println("requestUrl = " +requestUrl );
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
        // 如果请求成功   
        
        if (null != jsonObject) {  
            try {  
                accessToken = new AccessToken();  
                accessToken.setToken(jsonObject.getString("access_token"));  
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));  
            } catch (Exception e) {  
                accessToken = null;  
                // 获取token失败   
                System.out.println("获取token失败 errcode:{} errmsg:{}"+jsonObject.getInt("errcode") +jsonObject.getString("errmsg"));  
            }  
        }  
        return accessToken;  
        

    }  

    public static int createMenu(Menu menu, String accessToken) {  
        int result = 0;  
      
        // 拼装创建菜单的url   
        String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);  
        // 将菜单对象转换成json字符串   
        String jsonMenu = JSONObject.fromObject(menu).toString();  
        System.out.println("jsonMenu =" + jsonMenu);
        // 调用接口创建菜单   
        JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);  
        System.out.println("result =" + JSONObject.fromObject(jsonObject));
        if (null != jsonObject) {  
            if (0 != jsonObject.getInt("errcode")) {  
                result = jsonObject.getInt("errcode");  
                log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            } else {
            	System.out.println("创建菜单成功!!! ");
			}
            
        }  
      
        return result;  
    }  

 

    public static int sendTemplateMsg(String msg, String accessToken) {  
        int result = 0;  
      
        // 拼装创建菜单的url   
        String url = send_templateMsg_url.replace("ACCESS_TOKEN", accessToken);  
        // 将菜单对象转换成json字符串   
 
        System.out.println("msg =" + msg);
        // 调用接口创建菜单   
        JSONObject jsonObject = httpRequest(url, "POST", msg);  
      
        if (null != jsonObject) {  
            if (0 != jsonObject.getInt("errcode")) {  
                result = jsonObject.getInt("errcode");  
                log.error("发送模板消息 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            } else {
            	System.out.println("发送模板消息成功!!! ");
			}
            
        }  
      
        return result;  
    }  

    public static int sendNormalMsg(String msg, String accessToken,String func) {  
        int result = 0;  
      
        // 拼装创建菜单的url   
        String url = send_getUserMsg_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID", "ozkgEtxVKwoVwzobZnGVXZba0LQQ");  
         
        // 将菜单对象转换成json字符串   
 
        System.out.println("url =" + url);
        System.out.println("msg =" + msg);
        // 调用接口创建菜单   
        JSONObject jsonObject = httpRequest(url, func, msg);  
        System.out.println("return jsonObject =" + jsonObject.toString());
        if (null != jsonObject) {  
            if (0 != jsonObject.getInt("errcode")) {  
            	System.out.println("获取用户信息失败!!! ");
                result = jsonObject.getInt("errcode");  
                log.error("发送普通消息 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            } else {
            	System.out.println("发普通消息成功!!! ");
			}
            
        }  
      
        return result;  
    }  

    public static int listMenu(String accessToken) {  
        int result = 0;  
        System.out.println("listMenu........");
        // 拼装查询菜单的url   
        String url = menu_list_url.replace("ACCESS_TOKEN", accessToken);  
        // 将菜单对象转换成json字符串   
        String jsonMenu = null;
       
        // 调用接口查询菜单   
        JSONObject jsonObject = httpRequest(url, "GET", jsonMenu);  
        System.out.println("return result =" + jsonObject.toString());
        
        if (null != jsonObject) {  
            if (0 != jsonObject.getInt("errcode")) {  
            	System.out.println("查询菜单失败!!! ");
            	System.out.println("查询菜单失败!!! ： "+jsonObject.getInt("errcode"));
                result = jsonObject.getInt("errcode");  
                log.error("查询菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            } else {
            	System.out.println("查询菜单成功!!! ");
			}
            
        }
        return result;  
    }
    

    public static int uploadFile(String accessToken) {  
        int result = 0;  
        System.out.println("uploadFile........");
        // 拼装查询菜单的url   
        String url = upload_add_material.replace("ACCESS_TOKEN", accessToken);  
        // 将菜单对象转换成json字符串   
        String jsonMenu = null;
       
        // 调用接口查询菜单   
        try {
			JSONObject jsonObject = httpRequestPostFile(url,
														"image",
														"D:\\AppAttaches\\MsgMedia\\b5f4a4fa-720b-40e1-8068-5e8e19a64417.jpg"
														);  
			System.out.println("return result =" + jsonObject.toString());
			
			if (null != jsonObject) {  
			    if ( jsonObject.has("errcode")&&  (0 != jsonObject.getInt("errcode")) ) {  
			    	System.out.println("上传文件失败!!! ");
			    
			        result = jsonObject.getInt("errcode");  
			        log.error("上传文件 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
			    } else {
			    	System.out.println("上传文件成功!!! ");
				}
			    
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        return result;  
    }
    
    public static int deleteMenu(String accessToken) {  
        int result = 0;  
        System.out.println("deleteMenu........");
        // 拼装删除菜单的url   
        String url = menu_delete_url.replace("ACCESS_TOKEN", accessToken);  
        // 将菜单对象转换成json字符串   
        String jsonMenu = null;
       
        // 调用接口查询菜单   
        JSONObject jsonObject = httpRequest(url, "GET", jsonMenu);  
        System.out.println("return Menu =" + jsonObject.toString());
        
        if (null != jsonObject) {  
            if (0 != jsonObject.getInt("errcode")) {  
                result = jsonObject.getInt("errcode");  
                log.error("删除菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            } else {
            	System.out.println("删除菜单成功!!! ");
			}
            
        }
        return result;  
    }   

	public static JSONObject httpRequestPostFile(String requestUrl, String mediaType,
			String fileLocaton) throws Exception {
		// TODO Auto-generated method stub
		// TODO 自动生成方法存根
		 requestUrl = requestUrl+"&type="+mediaType;
		 System.out.println("requestUrl ="+requestUrl);
		 String endString="\r\n";
		 String twoHyphenString="--";
		 String boundaryString="*****";
		 String tempContentType="";
		 File file= new File(fileLocaton);
		 String fileName = file.getName();
		 
		 JSONObject jsonObject = null;  
	        StringBuffer buffer = new StringBuffer(); 
	        StringBuffer outBuffer  =new StringBuffer();
	        try {  

	  
	            URL url = new URL(requestUrl);  
	            HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  
	  
	            httpUrlConn.setDoOutput(true);  
	            httpUrlConn.setDoInput(true);  
	            httpUrlConn.setUseCaches(false);  
	            // 设置请求方式（GET/POST）   
	            httpUrlConn.setRequestMethod("POST");  
	            httpUrlConn.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundaryString );
	            
	            DataOutputStream dataOutputStream = new DataOutputStream(httpUrlConn.getOutputStream());
	            /*输出文件头*/
	            StringBuilder sBuilder = new StringBuilder();
	            sBuilder.append(twoHyphenString);
	            sBuilder.append(boundaryString);
	            sBuilder.append(endString);
	            sBuilder.append("Content-Disposition:form-data;name=\"file\";filename=\""+file.getName()+"\"\r\n");
	             tempContentType = new MimetypesFileTypeMap().getContentType(file);  
		        if (fileName.endsWith(".png")||fileName.endsWith(".jpg")) {  
		        	tempContentType = "image/png";  
		        }
		        if (tempContentType == null || tempContentType.equals("")) {  
		        	tempContentType = "application/octet-stream";  
		        }  	            
		        
	            sBuilder.append("Content-Type:" + tempContentType + "\r\n\r\n");
	            byte[] head=sBuilder.toString().getBytes("utf-8");
	            
	            dataOutputStream.write(head);
	            
	            /*输出文件*/
	            DataInputStream fileInputStream = new DataInputStream( new FileInputStream(file));
	            int bytes =0;
	            byte[] byfferOut= new byte[1024];
	            while (  ((bytes=fileInputStream.read(byfferOut))!=-1)) {
	            	dataOutputStream.write(byfferOut,0,bytes);
				}
	            fileInputStream.close();
	            
	            /*输出文件尾*/
	            byte[] foot=(endString+boundaryString+twoHyphenString+endString).getBytes("utf-8");
	            dataOutputStream.write(foot);
	            dataOutputStream.flush();
	            dataOutputStream.close();
	            
	
	            // 将返回的输入流转换成字符串   
	            InputStream inputStream = httpUrlConn.getInputStream();  
	            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
	            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
	  
	            String str = null;  
	            while ((str = bufferedReader.readLine()) != null) {  
	                buffer.append(str);  
	            }  
	            bufferedReader.close();  
	            inputStreamReader.close();  
	            // 释放资源   
	            inputStream.close();  
	            inputStream = null;  
	            httpUrlConn.disconnect();  
	            jsonObject = JSONObject.fromObject(buffer.toString());  
	        }    catch (ConnectException e) {   
	            RuntimeException exception = new RuntimeException("Weixin server connection timed out.");
	            throw exception;
	        } catch (Exception e) {
	            RuntimeException exception = new RuntimeException("https request error:{}"+e.getMessage() );
	            throw exception;
	        }  	        
	        return jsonObject;  
	}

   
}